package qmd.rgo.format.test;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;

import org.junit.Test;

import qmd.rgo.format.JSONFormatter;
import static org.junit.Assert.*;

@SuppressWarnings("javadoc")
public class JSONFormatterTestCase {
	
	@Test
	public void testTrue() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(true);
			locWriter.close();
			assertEquals("Written text is incorrect", "true", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testFalse() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(false);
			locWriter.close();
			assertEquals("Written text is incorrect", "false", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testNull() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).valueNull();
			locWriter.close();
			assertEquals("Written text is incorrect", "null", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testStringEmpty() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value("");
			locWriter.close();
			assertEquals("Written text is incorrect", "\"\"", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testStringNotEmpty() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value("\"\\\b\f\n\r\tabc123.=é/ا");
			locWriter.close();
			assertEquals("Written text is incorrect", "\"\\\"\\\\\\b\\f\\n\\r\\tabc123.=é/ا\"", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testIntegerZero() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(0);
			locWriter.close();
			assertEquals("Written text is incorrect", "0", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testIntegerPositive() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(1000);
			locWriter.close();
			assertEquals("Written text is incorrect", "1000", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testIntegerNegative() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(-1);
			locWriter.close();
			assertEquals("Written text is incorrect", "-1", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testDoubleZero() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(0.0);
			locWriter.close();
			assertEquals("Written text is incorrect", "0.0", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testDoublePositive() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(3.1416);
			locWriter.close();
			assertEquals("Written text is incorrect", "3.1416", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testDoubleNegative() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(-3.1416);
			locWriter.close();
			assertEquals("Written text is incorrect", "-3.1416", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testDoubleVeryBig() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(123456789.123456789);
			locWriter.close();
			assertEquals("Written text is incorrect", "1.2345678912345679E8", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testDoubleVerySmall() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(-0.00000123456789123456789);
			locWriter.close();
			assertEquals("Written text is incorrect", "-1.2345678912345679E-6", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testDoubleZeroWithExponent() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(0.0E10);
			locWriter.close();
			assertEquals("Written text is incorrect", "0.0", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testDoubleZeroMinusSign() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(-0.0);
			locWriter.close();
			assertEquals("Written text is incorrect", "-0.0", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testDoubleZeroPlusSign() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(+0.0);
			locWriter.close();
			assertEquals("Written text is incorrect", "0.0", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testDoubleWithNegativeExponent() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(1.23456789123456789E-15);
			locWriter.close();
			assertEquals("Written text is incorrect", "1.234567891234568E-15", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testDoubleWithPositiveExponent() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(1.23456789123456789E300);
			locWriter.close();
			assertEquals("Written text is incorrect", "1.234567891234568E300", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testBigInteger() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(new BigInteger("1000000000000000000000"));
			locWriter.close();
			assertEquals("Written text is incorrect", "1000000000000000000000", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testBigDecimal() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).value(new BigDecimal("-123456789123456789.123456789123456789"));
			locWriter.close();
			assertEquals("Written text is incorrect", "-123456789123456789.123456789123456789", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testObjectEmpty() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).objectWith().noMoreEntry();
			locWriter.close();
			assertEquals("Written text is incorrect", "{}", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testObjectOneNullEntry() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).objectWith().atEntry("toto").valueNull().noMoreEntry();
			locWriter.close();
			assertEquals("Written text is incorrect", "{\"toto\":null}", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testObjectOneBooleanEntry() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).objectWith().atEntry("toto").value(true).noMoreEntry();
			locWriter.close();
			assertEquals("Written text is incorrect", "{\"toto\":true}", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testObjectTwoEntries() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).objectWith()
				.atEntry("toto").value(true)
				.atEntry("titi").valueNull()
				.noMoreEntry();
			locWriter.close();
			assertEquals("Written text is incorrect", "{\"toto\":true,\"titi\":null}", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testArrayEmpty() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).arrayContaining()
				.noMoreItem();
			locWriter.close();
			assertEquals("Written text is incorrect", "[]", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testArrayOneNullEntry() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).arrayContaining()
				.itemHaving().valueNull()
				.noMoreItem();
			locWriter.close();
			assertEquals("Written text is incorrect", "[null]", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testArrayOneBooleanEntry() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).arrayContaining()
				.itemHaving().value(true)
				.noMoreItem();
			locWriter.close();
			assertEquals("Written text is incorrect", "[true]", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

	@Test
	public void testArrayTwoEntries() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).arrayContaining()
				.itemHaving().value(true)
				.itemHaving().valueNull()
				.noMoreItem();
			locWriter.close();
			assertEquals("Written text is incorrect", "[true,null]", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}
	
	@Test
	public void testObjectWithBooleanAndArray() {
		StringWriter locStringWriter = new StringWriter();
		BufferedWriter locWriter = new BufferedWriter(locStringWriter);
		try {
			JSONFormatter.writeTo(locWriter).objectWith()
				.atEntry("toto").value(true)
				.atEntry("titi").arrayContaining()
					.itemHaving().valueNull()
					.noMoreItem()
				.noMoreEntry();
			locWriter.close();
			assertEquals("Written text is incorrect", "{\"toto\":true,\"titi\":[null]}", locStringWriter.toString());
		} catch (IOException e) {
			fail("Unexpected IOException");
		}
	}

}
